﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Skywave.Windows.Forms
{
    public partial class ListEditor : UserControl
    {
        public ListEditor()
        {
            InitializeComponent();
        }

        [Category("Data")]
        public event EventHandler<ListEditorListViewItemBeforeAddEventArgs> ListViewItemBeforeAdd;
        [Category("Data")]
        public event EventHandler<ListEditorItemChangedEventArgs> ItemTextChanged;
        [Category("Data")]
        public event EventHandler<ListEditorItemDeleteEventArgs> ItemDeleted;
        [Category("Data")]
        public event EventHandler<ListEditorItemEditEventArgs> ItemEdit;
        [Category("Data")]
        public event EventHandler ItemPositionChanged, SelectionChanged;
        [Category("Data")]
        public event Func<object> ItemGetNew;

        /// <summary>
        /// VisibilityOfEditor Property
        /// </summary>
        [Category("Common")]
        public bool VisibilityOfEditor
        {
            get { return (editor_Panel == null) ? true : editor_Panel.Visible; }
            set { if (editor_Panel != null) editor_Panel.Visible = value; }
        }

        /// <summary>
        /// VisibilityOfDeleteCommand Property
        /// </summary>
        [Category("Common")]
        public bool VisibilityOfDeleteCommand
        {
            get { return (deleteSelected == null) ? true : deleteSelected.Visible; }
            set { if (deleteSelected != null) deleteSelected.Visible = value; }
        }

        /// <summary>
        /// VisibilityOfEditCommand Property
        /// </summary>
        [Category("Common")]
        public bool VisibilityOfEditCommand
        {
            get { return (editSelected == null) ? false : editSelected.Visible; }
            set { if (editSelected != null) editSelected.Visible = value; }
        }

        /// <summary>
        /// VisibilityOfPriorityCommands Property
        /// </summary>
        [Category("Common")]
        public bool VisibilityOfPriorityCommands
        {
            get { return (order_Up == null || order_Down == null) ? true : order_Up.Visible; }
            set
            {
                if (order_Up != null) order_Up.Visible = value;
                if (order_Down != null) order_Down.Visible = value;
            }
        }

        /// <summary>
        /// MultiSelect Property
        /// </summary>
        [Category("Common")]
        public bool MultiSelect
        {
            get { return (itemsList == null) ? true : itemsList.MultiSelect; }
            set { if (itemsList != null) itemsList.MultiSelect = value; }
        }

        /// <summary>
        /// Items Property
        /// </summary>
        [Browsable(false)]
        public List<object> Items
        {
            get { return _Items; }
            set { _Items = value; }
        }
        private List<object> _Items = new List<object>();

        /// <summary>
        /// SelectedItems Property
        /// </summary>
        [Browsable(false)]
        public List<object> SelectedItems
        {
            get
            {
                List<object> r = new List<object>();
                for (int i = 0; i < itemsList.SelectedItems.Count; i++)
                {
                    r.Add(itemsList.SelectedItems[i].Tag);
                }
                return r;
            }
            set
            {
                itemsList.SelectedItems.Clear();
                foreach (object feItem1 in value)
                {
                    ListViewItem item1 = (from x1 in itemsList.Items.Cast<ListViewItem>()
                                          where x1.Tag == feItem1
                                          select x1).FirstOrDefault();
                    if (item1 != null)
                        item1.Selected = true;
                }
            }
        }

        /// <summary>
        /// SelectedIndex Property
        /// </summary>
        [Browsable(false)]
        public int SelectedIndex
        {
            get { return (itemsList == null || itemsList.SelectedIndices.Count == 0) ? -1 : itemsList.SelectedIndices[0]; }
            set
            {
                if (itemsList != null && (itemsList.SelectedIndices.Count != 1 || itemsList.SelectedIndices[0] != value))
                {
                    itemsList.SelectedIndices.Clear();
                    itemsList.SelectedIndices.Add(value);
                }
            }
        }

        /// <summary>
        /// SelectedItem Property
        /// </summary>
        [Browsable(false)]
        public object SelectedItem
        {
            get { return (itemsList == null || itemsList.SelectedItems.Count == 0) ? null : itemsList.SelectedItems[0].Tag; }
            set
            {
                if (itemsList != null && (itemsList.SelectedItems.Count != 1 || itemsList.SelectedItems[0].Tag != value))
                {
                    SelectedItems = new List<object>() { value };
                }
            }
        }

        ///// <summary>
        ///// DisplayMemberPath Property
        ///// </summary>
        //[Category("Common")]
        //public string DisplayMemberPath
        //{
        //    get { return (itemsList == null) ? null : itemsList.DisplayMemberPath; }
        //    set { if (itemsList != null) itemsList.DisplayMemberPath = value; }
        //}

        private bool _AutoConfirmOnDelete = true;
        /// <summary>
        /// AutoConfirmOnDelete Property
        /// </summary>
        [Category("Common")]
        public bool AutoConfirmOnDelete
        {
            get { return _AutoConfirmOnDelete; }
            set { _AutoConfirmOnDelete = value; }
        }

        /// <summary>
        /// View Property
        /// </summary>
        [Browsable(false)]
        public View View
        {
            get { return (itemsList == null) ? View.List : itemsList.View; }
            set { if (itemsList != null) itemsList.View = value; }
        }

        /// <summary>
        /// Columns Property
        /// </summary>
        public ListView.ColumnHeaderCollection Columns
        {
            get { return (itemsList == null) ? null : itemsList.Columns; }
        }

        private void AddListLiveItem(object item1)
        {
            ListViewItem listItem1;
            listItem1 = new ListViewItem(item1.ToString());
            listItem1.Tag = item1;
            if (ListViewItemBeforeAdd != null)
                ListViewItemBeforeAdd(this, new ListEditorListViewItemBeforeAddEventArgs(listItem1));
            itemsList.Items.Add(listItem1);
        }

        public void RefreshList()
        {
            itemsList.Items.Clear();
            if (_Items == null) return;
            object item1;
            for (int i = 0; i < _Items.Count; i++)
            {
                item1 = _Items[i];
                AddListLiveItem(item1);
            }
        }

        private void itemsList_SelectedIndexChanged(object sender, EventArgs e)
        {
            Raise_SelectionChanged();
        }

        bool isSelectionChangeDisabled = false;
        private void Raise_SelectionChanged()
        {
            if (itemsList.SelectedItems.Count == 0)
            {
                isUpdateByProgram = true;
                sel_Text.Text = "";
                isUpdateByProgram = false;
                sel_Text.Enabled = false;
                deleteSelected.Enabled = false;
                editSelected.Enabled = false;
                order_Up.Enabled = false;
                order_Down.Enabled = false;
            }
            else if (itemsList.SelectedItems.Count > 1)
            {
                isUpdateByProgram = true;
                sel_Text.Text = "";
                isUpdateByProgram = false;
                sel_Text.Enabled = false;
                deleteSelected.Enabled = true;
                editSelected.Enabled = true;
                order_Up.Enabled = true;
                order_Down.Enabled = true;
            }
            else
            {
                isUpdateByProgram = true;
                sel_Text.Text = SelectedItem.ToString();
                isUpdateByProgram = false;
                sel_Text.Enabled = true;
                deleteSelected.Enabled = true;
                editSelected.Enabled = true;
                order_Up.Enabled = true;
                order_Down.Enabled = true;
            }

            if (isSelectionChangeDisabled) return;
            if (SelectionChanged != null)
                SelectionChanged(this, new EventArgs());
        }

        private bool isUpdateByProgram = false;

        private void sel_Text_TextChanged(object sender, EventArgs e)
        {
            if (isUpdateByProgram) return;
            if (itemsList.SelectedItems.Count == 1)
            {
                itemsList.BeginUpdate();
                ListEditorItemChangedEventArgs arg1 = new ListEditorItemChangedEventArgs();
                arg1.Item = SelectedItem;
                arg1.NewText = sel_Text.Text;
                if (ItemTextChanged != null)
                    ItemTextChanged(this, arg1);
                itemsList.EndUpdate();
            }
        }

        private void addNew_Click(object sender, EventArgs e)
        {
            if (ItemGetNew != null)
            {
                object newObj = ItemGetNew();
                if (newObj != null)
                {
                    if (newObj is List<object>)
                    {
                        foreach (object fe1 in newObj as List<object>)
                        {
                            AddListLiveItem(fe1);
                            _Items.Add(fe1);
                        }
                        SelectedItem = (newObj as List<object>).Last();
                        sel_Text.Focus();
                        sel_Text.SelectAll();
                    }
                    else
                    {
                        AddListLiveItem(newObj);
                        _Items.Add(newObj);
                        SelectedItem = newObj;
                        sel_Text.Focus();
                        sel_Text.SelectAll();
                    }
                }
            }
        }

        private void deleteSelected_Click(object sender, EventArgs e)
        {
            if (itemsList.SelectedItems.Count <= 0) return;
            if (AutoConfirmOnDelete == false ||
                MessageBox.Show(this.ParentForm, Properties.Resources.General_Confirm_SelectedItemsDelete, "", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign) == DialogResult.Yes)
            {
                ListEditorItemDeleteEventArgs args = new ListEditorItemDeleteEventArgs();
                args.Items = itemsList.SelectedItems.Cast<object>().ToList();
                if (ItemDeleted != null)
                {
                    ItemDeleted(this, args);
                    if (args.IsCanceled) return;
                    List<object> toRemove = new List<object>();
                    foreach (object item in itemsList.SelectedItems)
                        toRemove.Add(item);
                    isSelectionChangeDisabled = true;
                    foreach (object item in toRemove)
                    {
                        itemsList.Items.Remove((from x1 in itemsList.Items.Cast<ListViewItem>()
                                                where x1.Tag == item
                                                select x1).FirstOrDefault());
                        _Items.Remove(item);
                    }
                    isSelectionChangeDisabled = false;
                    Raise_SelectionChanged();
                }
            }
        }

        private void order_Up_Click(object sender, EventArgs e)
        {
            if (itemsList.SelectedItems.Count > 0)
            {
                itemsList.BeginUpdate();
                List<object> newSorted = new List<object>();
                object item1;
                int indexToInsert = SelectedIndex - 1;
                if (indexToInsert >= 0)
                {
                    for (int i = 0; i < itemsList.Items.Count; i++)
                    {
                        if (i == indexToInsert)
                        {
                            for (int j = 0; j < itemsList.SelectedItems.Count; j++)
                            {
                                newSorted.Add(itemsList.SelectedItems[j].Tag);
                            }
                        }

                        item1 = itemsList.Items[i].Tag;
                        if (!SelectedItems.Contains(item1))
                            newSorted.Add(item1);
                    }

                    itemsList.Items.Clear();
                    for (int i = 0; i < newSorted.Count; i++)
                    {
                        AddListLiveItem(newSorted[i]);
                    }
                }
                itemsList.EndUpdate();
                _Items = newSorted;
                if (ItemPositionChanged != null)
                    ItemPositionChanged(this, new EventArgs());
            }
        }

        private void order_Down_Click(object sender, EventArgs e)
        {
            if (itemsList.SelectedItems.Count > 0)
            {
                SortedDictionary<int, object> newSorted = new SortedDictionary<int, object>();
                itemsList.BeginUpdate();
                object item1;
                int curIndex;
                int indexToInsert = SelectedIndex + 1;

                if ((indexToInsert + itemsList.SelectedItems.Count - 1) < itemsList.Items.Count)
                {
                    //Add selected items in new positions
                    for (int i = 0; i < itemsList.SelectedItems.Count; i++)
                    {
                        newSorted.Add(indexToInsert + i, itemsList.SelectedItems[i].Tag);
                    }

                    //Put other items in free spaces
                    curIndex = 0;
                    for (int i = 0; i < itemsList.Items.Count; i++)
                    {
                        item1 = itemsList.Items[i].Tag;
                        if (!SelectedItems.Contains(item1))
                        {
                            while (newSorted.ContainsKey(curIndex)) curIndex++;
                            newSorted.Add(curIndex, item1);
                            curIndex++;
                        }
                    }

                    //Create the new List
                    itemsList.Items.Clear();
                    _Items.Clear();
                    for (int i = 0; i < newSorted.Count; i++)
                    {
                        AddListLiveItem(newSorted[i]);
                        _Items.Add(newSorted[i]);
                    }
                }
                itemsList.EndUpdate();
                if (ItemPositionChanged != null)
                    ItemPositionChanged(this, new EventArgs());
            }
        }

        private void editSelected_Click(object sender, EventArgs e)
        {
            if (itemsList.SelectedItems.Count <= 0) return;
            ListEditorItemEditEventArgs args = new ListEditorItemEditEventArgs();
            args.Items = SelectedItems;
            if (ItemEdit != null)
            {
                ItemEdit(this, args);
                if (args.IsCanceled) return;
                RefreshList();
            }
        }

    }
}
